<template>
  <div class="map-container">
    <div ref="mapContainerDom" class="map-container"></div>
    <div class="map-ctl">
      <button @click="mapExport()">全图导出</button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { OlUtil } from '../../lib/index'
import { onMounted, nextTick, ref, onBeforeUnmount } from 'vue'
import { Map } from 'ol'
import { get, Projection } from 'ol/proj'
import { WindLayer } from '../../lib/utils/olWind'
import windData from '../data/gfs.json'
import { WMTS, XYZ } from 'ol/source'
const mapConfig = {
  defaultShowMap: 'img',
  imgMapType: 'WMTS',
  imgMapUrl: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer',
  vecMapType: 'XYZ',
  vecMapUrl: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
  projectionCode: 'EPSG:3857',
  center: [81.8018641, 41.7792352],
  zoom: 15,
  maxZoom: 20,
  minZoom: 4,
  imgBaseUrl: ''
}

const olutil = new OlUtil()
let map: Map
const mapLoaded = ref(false)
let observer: ResizeObserver | null = null // 地图dom大小监听
const mapContainerDom = ref() // 地图容器

let mapProjection: Projection | undefined
const projectionCode = mapConfig.projectionCode || 'EPSG:3857'
if (projectionCode === 'EPSG:4490') {
  mapProjection = olutil.defineProjection_4490()
} else {
  mapProjection = get(projectionCode) as Projection
}
let ram: any
if (mapProjection) {
  ram = olutil.getResolutionsAndMids(mapProjection) // 获取分辨率和层级矩阵
}
const showMapType = ref(mapConfig.defaultShowMap) // 当前显示底图类型

let windLayer: WindLayer | undefined

// 加载地图
const loadMap = (id: string, mapUrl: string, type: string) => {
  let layer
  if (type === 'XYZ') {
    layer = olutil.loadXYZLayer({
      id,
      url: mapUrl,
      projection: mapConfig.projectionCode
    })
  } else if (type === 'WMTS') {
    layer = olutil.loadWMTSLayer({
      id,
      url: mapUrl,
      matrixSet: 'default028mm',
      projection: mapProjection,
      resolutions: ram.resolutions,
      matrixIds: ram.matrixIds
    })
  }
  layer && layer.setVisible(mapConfig.defaultShowMap === id)
  return layer
}
// 初始化地图
const initMap = () => {
  const vecMapLayer = loadMap('vec', mapConfig.vecMapUrl, mapConfig.vecMapType)
  const imgMapLAyer = loadMap('img', mapConfig.imgMapUrl, mapConfig.imgMapType)

  map = olutil.initMap(mapContainerDom.value, {
    // projection: 'EPSG:3857',
    center: mapConfig.center || [87.62, 43.83],
    zoom: mapConfig.zoom || 8,
    minZoom: mapConfig.minZoom || 6,
    maxZoom: mapConfig.maxZoom || 18,
    layers: [imgMapLAyer!, vecMapLayer!]
  })
}

// 重置地图
const resetMap = () => {
  const pathLayer = olutil.getLayer('line')
  if (pathLayer) {
    olutil.goToLayer('line')
  } else {
    const center = mapConfig.center || [81.8018641, 41.7792352]
    const zoom = mapConfig.zoom || 8
    const duration = 500
    olutil.setCenterAndZoom({ center, zoom, duration })
  }
}

// 切换底图
const changeMap = (id: string) => {
  if (showMapType.value === id) {
    return
  }
  // 隐藏旧底图
  const lastedMap = olutil.getLayer(showMapType.value)
  lastedMap && lastedMap.setVisible(false)
  // 显示选中底图
  const nowMap = olutil.getLayer(id)
  nowMap && nowMap.setVisible(true)
  // 记录选中底图
  showMapType.value = id
}

// 加载风场
const loadWindLayer = () => {
  createWindLayer(windData)

  // fetch('https://sakitam-1255686840.cos.ap-beijing.myqcloud.com/public/codepen/json/out.json')
  //   .then((res) => res.json())
  //   .then((res) => {
  //     res.forEach((item:any) => {
  //       // 翻转Y轴
  //       item.header.ny = item.header.ny || item.header.nLat
  //       item.header.dy = item.header.dy || item.header.dLat
  //       item.header.ly = item.header.ly || item.header.lat0
  //       item.header.ly = item.header.ly + (item.header.ny - 1) * item.header.dy
  //       item.header.dy = -item.header.dy
  //     })
  //     createWindLayer(res)
  //     console.log(res, '---res')
  //   })
}
// 创建风场图层
const createWindLayer = (windData:any) => {
  windLayer = new WindLayer(windData,
    {
      forceRender: true, // 地图缩放时强制渲染，防止卡顿
      fieldOptions: {
      },
      windOptions: {
        colorScale: [
          'rgb(36,104, 180)',
          'rgb(60,157, 194)',
          'rgb(128,205,193 )',
          'rgb(151,218,168 )',
          'rgb(198,231,181)',
          'rgb(238,247,217)',
          'rgb(255,238,159)',
          'rgb(252,217,125)',
          'rgb(255,182,100)',
          'rgb(252,150,75)',
          'rgb(250,112,52)',
          'rgb(245,64,32)',
          'rgb(237,45,28)',
          'rgb(220,24,32)',
          'rgb(180,0,35)'
        ],
        globalAlpha: 0.9, // 粒子透明度
        lineWidth: 2, // 线宽,
        velocityScale: 1 / 50, // 粒子速度
        maxAge: 60, // 存活最大帧数
        frameRate: 16, // 每16帧绘制一次
        useCoordsDraw: true, // 使用外部传入的坐标系统，默认是 `true`；某些场景下我们可能直接使用像素坐标。
        generateParticleOption: true,
        paths: 1000, // 粒子数量
      }
    }
  )
  map && map.addLayer(windLayer)
  console.log(windLayer, '---windLayer')
}

// 更新粒子数量
const updateParticleCount = (zoom:number) => {
  if (!map || !windLayer) return

  const particleCount = Math.max(1000, (20 - zoom) * 100)
  windLayer.setWindOptions({
    paths: particleCount
  })
}

// 注册地图事件
const registerMapEvent = () => {
 // 监听地图层级变化
  map && map.on('moveend', () => {
    const zoom = map!.getView().getZoom() || 0
    updateParticleCount(zoom)
  }) 
}

onMounted(() => {
  initMap()
  nextTick(() => {
    map &&
      map.once('rendercomplete', () => {
        mapLoaded.value = true
        // 监听地图dom大小变化
        observer = new ResizeObserver(() => {
          map && map.updateSize()
        })
        observer.observe(mapContainerDom.value)

        loadWindLayer()
        registerMapEvent()
      })
  })
})

// 生成当前时间
const getCurrentTime = () => {
  // 生成年月日时分秒格式的时间戳
  const now = new Date()
  const year = now.getFullYear()
  const month = String(now.getMonth() + 1).padStart(2, '0')
  const day = String(now.getDate()).padStart(2, '0')
  const hours = String(now.getHours()).padStart(2, '0')
  const minutes = String(now.getMinutes()).padStart(2, '0')
  const seconds = String(now.getSeconds()).padStart(2, '0')
  const timestamp = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`
  return timestamp
}

// 全图导出
const mapExport = () => {
  if (!map) return

  // 获取地图的canvas元素
  const canvas = map.getTargetElement().querySelector('canvas') as HTMLCanvasElement

  // 创建临时canvas
  const tempCanvas = document.createElement('canvas')
  const ctx = tempCanvas.getContext('2d') as CanvasRenderingContext2D

  // 设置临时canvas尺寸
  tempCanvas.width = canvas.width
  tempCanvas.height = canvas.height

  // 绘制到临时canvas
  ctx.drawImage(canvas, 0, 0)

  // 导出
  const link = document.createElement('a')
  
  link.download = `map_${getCurrentTime()}.png`
  link.href = tempCanvas.toDataURL('image/png')
  link.click()
}
onBeforeUnmount(() => {
  try {
    observer && observer.unobserve(mapContainerDom.value) // 移除监听
  } catch (err) {
    console.log(err)
  }
})
</script>
<script lang="ts">
export default {
  name: 'WindMap'
}
</script>
<style lang="scss" scoped>
.map-container {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
  .base-map-ctl {
    position: absolute;
    right: 0.2rem;
    bottom: 0.1rem;
    display: flex;
    background: rgba(31, 30, 30, 0.5);
    box-shadow: 2px 2px rgba(0, 0, 0, 0.4);
    border-radius: 3px;
    padding: 0.1rem;
    .map-type-img {
      height: 60px;
      width: 86px;
      cursor: pointer;
      border: 2px solid transparent;
    }

    .map-type-img-selected {
      border: 2px solid #2d8cf0;
    }
    .map-type-img:last-child {
      margin-left: 0.05rem;
    }
  }
  .map-ctl {
    position: absolute;
    left: 0.2rem;
    top: 0.2rem;
    display: flex;
    flex-direction: column;
    background: rgba(0, 0, 0, 0.5);
    padding: 0.1rem 0.08rem;
    border-radius: 4px;
    .map-ctl-item {
      margin-bottom: 0.1rem;
    }
    .map-ctl-item:last-child {
      margin-bottom: 0;
    }
  }
  .get-position-title {
    position: absolute;
    border: 1px solid #2d8cf0;
    background: white;
    padding: 0 4px;
    border-radius: 5px;
    pointer-events: none;
  }
}
</style>
